#include<semaphore.h>
#include<stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <pthread.h>
#include<fcntl.h>
#include<unistd.h>
#include<signal.h>
typedef void* (*Func)(void *);
int fds[4];
sem_t sem[4];
pthread_t p[4];
void open_file()
{
    char temp[1]="A";
    for(int i=0;i<4;i++)
    {
        temp[0]='A';
        temp[0]=temp[0]+i;
        if((fds[i]=open(temp,O_RDWR|O_CREAT|O_APPEND|O_TRUNC,0655))< 0)
        {
            perror("open error\n");
            exit(1);
        }
    }

}
void* write_A(void *arg)
{
    char temp='A';
    int flag=0;
    while(1)
    {
        sem_wait(&sem[0]);
        for(int i=0;i<4;i++)
        {
            if(flag!=0||i<=0)
            {
                write(fds[i],&temp,1);
            }
        }
        flag=1;
        sem_post(&sem[1]);
    }
}
void* write_B(void *arg)
{
    char temp='B';
    int flag=0;
    while(1)
    {
        sem_wait(&sem[1]);
        for(int i=0;i<4;i++)
        {
            if(flag!=0||i<=1)
            {
                write(fds[i],&temp,1);
            }
        }
        flag=1;
        sem_post(&sem[2]);
    }
}
void* write_C(void *arg)
{
    int flag=0;
    char temp='C';
    while(1)
    {
        sem_wait(&sem[2]);
        for(int i=0;i<4;i++)
        {
            if(flag!=0||i<=2)
            {
                write(fds[i],&temp,1);
            }
        }
        flag=1;
        sem_post(&sem[3]);
    }
}
void* write_D(void *arg)
{
    int flag=0;
    char temp='D';
    while(1)
    {
        sem_wait(&sem[3]);
        for(int i=0;i<4;i++)
        {
           write(fds[i],&temp,1);
        }
        flag=1;
        sem_post(&sem[0]);
    }
}
void my_exit(int sig)
{
    for(int i=0;i<4;i++)
    {
        pthread_cancel(p[i]);
        sem_destroy(&sem[i]);
    }
}
int main(int argc,char **argv)
{
    open_file();
    Func func[4]={write_A,write_B,write_C,write_D};
    signal(SIGINT,my_exit);
    for(int i=0;i<4;i++)
    {
        if(i==0)
        {
            sem_init(&sem[i],0,1);
        }
        else{
        sem_init(&sem[i],0,0);
        }
    }
    for(int i=0;i<4;i++)
    {
        pthread_create(&p[i],NULL,func[i],NULL);
        pthread_detach(p[i]);
    }
    pause();
    return 0;
}
